package fr.ssd.sic.ui;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.IOException;

import javax.mail.BodyPart;
import javax.mail.Folder;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Message.RecipientType;
import javax.mail.internet.MimeMultipart;
import javax.swing.BorderFactory;
import javax.swing.DefaultListModel;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextArea;
import javax.swing.JTree;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.table.TableColumnModel;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.TreePath;

import com.sun.mail.util.BASE64DecoderStream;

import fr.ssd.sic.config.Configurator;
import fr.ssd.sic.imap.ListFoldersCmd;
import fr.ssd.sic.imap.ListMessagesCmd;

public class SimUi {

	// Header values. Note the table model provides
	// string column names that are the default header
	// values.
	final Object[] tableHeaders = new Object[] { "", "Subject", "Sender",
			"Date" };

	final JFrame frame = new JFrame("SIC");
	final Folder folder;

	public SimUi(final Folder folder) {
		this.folder = folder;

		try {
			UIManager.setLookAndFeel(Configurator.lookAndFeel);
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		} catch (InstantiationException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		} catch (UnsupportedLookAndFeelException e) {
			e.printStackTrace();
		}
		/* Turn off metal's use bold fonts */
		// UIManager.put("swing.boldMetal", Boolean.FALSE);
	}

	/**
	 * Create the GUI and show it.
	 */
	public void createAndShowGUI() {

		// Schedule a job for the event-dispatching thread:
		// creating and showing this application's GUI.
		javax.swing.SwingUtilities.invokeLater(new Runnable() {
			public void run() {
				frame.setPreferredSize(new Dimension(900, 600));
				createComponents();
				// Display the window.
				frame.pack();
				frame.setVisible(true);
			}

		});
	}

	protected void createComponents() {

		// Create and set up the window.

		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

		DefaultMutableTreeNode tree = new DefaultMutableTreeNode();
		try {
			new ListFoldersCmd().execute(tree, folder);
		} catch (MessagingException e) {
			e.printStackTrace();
		}

		final JTree jtree = new JTreeFolder(tree);
		jtree.setCellRenderer(new MultiLineCellRenderer());
		jtree.setPreferredSize(new Dimension(200, 400));

		JScrollPane spTree = new JScrollPane();
		spTree.getViewport().add(jtree);

		final MailTableModel mailTable = new MailTableModel();
		final JTable table = new JTable(mailTable);
		TableColumnModel tcm = table.getColumnModel();

		// Add the custom header renderer

		int columns = tableHeaders.length;
		for (int i = 0; i < columns; i++) {
			tcm.getColumn(i).setHeaderValue(tableHeaders[i]);
		}
		tcm.getColumn(0).setPreferredWidth(30);
		tcm.getColumn(0).setMaxWidth(30);
		tcm.getColumn(1).setPreferredWidth(370);
		tcm.getColumn(2).setPreferredWidth(200);
		tcm.getColumn(3).setPreferredWidth(100);

		JScrollPane spTable = new JScrollPane(table);

		JButton newMail = new JButton("Compose");
		JButton configuration = new JButton("Configuration");
		
		JPanel menu = new JPanel();
		FlowLayout fl = new FlowLayout();
		fl.setAlignment(FlowLayout.LEFT);
		menu.setLayout(fl);
		menu.add(newMail);
		menu.add(configuration);
		frame.add(menu, BorderLayout.BEFORE_FIRST_LINE);
		frame.add(spTree, BorderLayout.LINE_START);
		frame.add(spTable, BorderLayout.CENTER);

		table.addMouseListener(new MouseAdapter() {
			public void mouseClicked(MouseEvent me) {
				int row = table.getSelectedRow();
				System.out.println("Selected row : " + row);
				Message message = mailTable.getMessage(row);
				createMailFrame(message);
			}
		});

		jtree.addMouseListener(new MouseAdapter() {
			public void mouseClicked(MouseEvent me) {
				TreePath tp = jtree.getPathForLocation(me.getX(), me.getY());
				if (tp != null) {
					DefaultMutableTreeNode node = (DefaultMutableTreeNode) tp
							.getLastPathComponent();
					Folder folder = (Folder) node.getUserObject();
					System.out.println("Selected folder : " + folder.getName());
					try {
						mailTable
								.setData(new ListMessagesCmd().execute(folder));
					} catch (MessagingException e) {
						e.printStackTrace();
					}
				}
			}
		});
	}

	protected void createMailFrame(Message message) {
		try {
			final JFrame frame = new JFrame(message.getSubject());
			frame.setPreferredSize(new Dimension(900, 600));
			frame.setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE);
			JTextArea text = new JTextArea(20, 55);
			JLabel header = new JLabel();
			header.setBorder(BorderFactory.createTitledBorder("Message #"
					+ message.getMessageNumber()));

			DefaultListModel files = new DefaultListModel();
			JList filesJList = new JList(files);

			StringBuilder headerText = new StringBuilder();

			headerText.append("<html>");
			appendHeaderElement(headerText, "From: ", message.getFrom());
			appendHeaderElement(headerText, "To: ", message
					.getRecipients(RecipientType.TO));
			appendHeaderElement(headerText, "CC: ", message
					.getRecipients(RecipientType.CC));
			appendHeaderElement(headerText, "BCC: ", message
					.getRecipients(RecipientType.BCC));
			headerText.append("</html>");

			header.setText(headerText.toString());

			text.setText(formatContent(message, files));
			JScrollPane spText = new JScrollPane(text);
			JScrollPane spFiles = new JScrollPane(filesJList);
			frame.add(header, BorderLayout.BEFORE_FIRST_LINE);
			frame.add(spText, BorderLayout.CENTER);
			if (!files.isEmpty()) {
				frame.add(spFiles, BorderLayout.LINE_END);
			}

			// Display the window.
			frame.pack();
			frame.setVisible(true);

		} catch (IOException e) {
			e.printStackTrace();
		} catch (MessagingException e) {
			e.printStackTrace();
		}

	}

	private void appendHeaderElement(StringBuilder headerText, String label,
			Object obj) {
		headerText.append("<p>");
		headerText.append(label);
		if (obj != null) {
			if (obj.getClass().isArray()) {
				for (Object o : (Object[]) obj) {
					headerText.append(o.toString() + " ");
				}
			} else {
				headerText.append(obj.toString() + " ");
			}
		}
		headerText.append("</p>");
	}

	private String formatContent(Message message, DefaultListModel files)
			throws IOException, MessagingException {
		StringBuilder sb = new StringBuilder();

		if (message.getContent() instanceof MimeMultipart) {
			MimeMultipart mm = (MimeMultipart) message.getContent();
			for (int i = 0; i < mm.getCount(); i++) {
				BodyPart bp = mm.getBodyPart(i);
				if (bp.getContent() instanceof BASE64DecoderStream) {
					// BASE64DecoderStream base64dec =
					// (BASE64DecoderStream)bp.getContent();
					files.addElement(bp.getFileName());
				} else {
					sb.append(bp.getContent().toString());
					sb.append("\n----- MultiPart -----\n");
				}
			}
		} else {
			sb.append(message.getContent());
		}
		return sb.toString();
	}

}
